package com.xs.gis.cover.coverImpl;

import com.xs.gis.cover.FileCover;
import com.xs.gis.cover.SimpleCover;
import com.xs.gis.domain.geojson.GeoFeature;
import com.xs.gis.domain.geojson.GeoJsonFeature;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.FeatureLayer;
import org.geotools.map.MapContent;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.renderer.lite.StreamingRenderer;
import org.geotools.styling.Style;
import org.geotools.styling.StyleBuilder;
import org.geotools.styling.StyleFactory;
import org.geotools.styling.Symbolizer;
import org.geotools.xml.styling.SLDParser;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ParseException;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static com.xs.gis.enums.CoverConstant.SHP_GEOM_KEY;

/**
 * @program: cdgis_geotoolsplus
 * @description:
 * @author: w
 * @create: 2023-08-17 17:43
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ImgCover implements SimpleCover, FileCover {

    /**
     * 文件路径,geom没有路径的时候构造方法传图
     */
    private String imgPath;

    /**
     * 样式路径,没有路径的时候默认样式
     */
    private String stylePath ;

    /**
     * 宽度,默认800
     */
    private int width = 800;

    /**
     * 高度,默认600
     */
    private int height = 600;


    /**
     * 样式,传入自定义样式
     */
    private Style style;

    public ImgCover(String imgPath) {
        this.imgPath = imgPath;
    }

    public ImgCover(String imgPath, String stylePath) {
        this.imgPath = imgPath;
        this.stylePath = stylePath;
    }



    @Override
    public Geometry dataToGeometry(String data) throws ParseException {
        throw new  RuntimeException("不支持当前方法");
    }
    // MapContent 是 GeoTools 中用于管理地图内容和渲染状态的核心类，它封装了地图的图层、样式、坐标系、视图范围等关键信息。
    // 作为地图渲染的上下文容器，MapContent 提供了统一的接口来管理地图要素的显示逻辑，是连接数据层与可视化层的桥梁。
    /**
     * geometry 转图片
     * @param geometry 空间数据
     * @return 图片路径
     */
    @Override
    public String geometryToData(Geometry geometry) {

        try {
            MapContent map = new MapContent();

            // 创建 FeatureCollection
            SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
//            typeBuilder.setName("Feature"); // 设置要素类型名称

            ArrayList<SimpleFeature> features = new ArrayList<>();
            typeBuilder.add(SHP_GEOM_KEY, Geometry.class);
            SimpleFeatureType featureType = typeBuilder.buildFeatureType();
            SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType);
            featureBuilder.set(SHP_GEOM_KEY, geometry);
            SimpleFeature simpleFeature = featureBuilder.buildFeature(UUID.randomUUID().toString());
            features.add(simpleFeature);

            ListFeatureCollection featureCollection = new ListFeatureCollection(featureType, features);
            Style style = genStyle(geometry);

            //创建layer
            org.geotools.map.Layer layer = new FeatureLayer(featureCollection, style);
            map.addLayer(layer);


            Envelope envelopeInternal = geometry.getEnvelopeInternal();

            CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84;

            // 设置地图区域并渲染地图
            ReferencedEnvelope mapArea = new ReferencedEnvelope(envelopeInternal.getMinX(),envelopeInternal.getMaxX(), envelopeInternal.getMinY(), envelopeInternal.getMaxY(), crs);


            StreamingRenderer sr = new StreamingRenderer();
            sr.setMapContent(map);
            // 初始化输出图像
            // 设置图片大小并创建缓冲图像
            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics g = bi.getGraphics();
            //设置背景色
            ((Graphics2D) g).setBackground(Color.WHITE);

            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            Rectangle rect = new Rectangle(0, 0, width, height);
            // 绘制地图
            sr.paint((Graphics2D) g, rect, mapArea);
            //将BufferedImage变量写入文件中。
            ImageIO.write(bi, "png", new File(imgPath));


        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        return imgPath;
    }

    /**
     * feature转为图片
     * @param feature 空间数据
     * @param filePath 图片路径
     * @return
     * @throws IOException
     */
    @Override
    public String featureToFile(GeoJsonFeature feature, String filePath) throws IOException {

        MapContent map = new MapContent();

        // 创建 FeatureCollection
        SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
        typeBuilder.setName(feature.getLayerName()); // 设置要素类型名称

        ArrayList<SimpleFeature> features = new ArrayList<>();

        typeBuilder.add(SHP_GEOM_KEY, Geometry.class);

        SimpleFeatureType featureType = typeBuilder.buildFeatureType();
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType);
        List<GeoFeature> featuresList = feature.getFeatures();

        featuresList.forEach(x->{
            Geometry geometry = x.formatGeometry();
            featureBuilder.set(SHP_GEOM_KEY, geometry);
            SimpleFeature simpleFeature = featureBuilder.buildFeature(UUID.randomUUID().toString());
            features.add(simpleFeature);
        });

        ListFeatureCollection featureCollection = new ListFeatureCollection(featureType, features);
        ReferencedEnvelope bounds = featureCollection.getBounds();
        CoordinateReferenceSystem crs = bounds.getCoordinateReferenceSystem();

        ReferencedEnvelope mapArea = new ReferencedEnvelope(bounds.getMinX(),bounds.getMaxX(), bounds.getMinY(), bounds.getMaxY(), crs);

        Geometry geometry = featuresList.get(0).formatGeometry();
        //样式
        Style style = genStyle(geometry);

        //创建layer
        org.geotools.map.Layer layer = new FeatureLayer(featureCollection, style);
        map.addLayer(layer);


        StreamingRenderer sr = new StreamingRenderer();
        sr.setMapContent(map);
        // 初始化输出图像
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics g = bi.getGraphics();
        ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        Rectangle rect = new Rectangle(0, 0, width, height);

        sr.paint((Graphics2D) g, rect, mapArea);

        if (StringUtils.isBlank(imgPath)){
            imgPath = filePath;
        }
        ImageIO.write(bi, "png", new File(imgPath));
        return imgPath;
    }

    /***
     * 初始化样式
     * @param geometry 空间数据
     * @return
     */
    private  Style genStyle(Geometry geometry) {

        if (style!=null){
            return style;
        }
        //样式文件路径
        if (StringUtils.isNotBlank(stylePath)){
            File sldFile = new File(stylePath);
            StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory();
            SLDParser stylereader = null;
            try {
                stylereader = new SLDParser(styleFactory, sldFile.toURI().toURL());
                Style[] stylearray = stylereader.readXML();
                style = stylearray[0];
            } catch (IOException e) {
                throw new RuntimeException("样式文件及解析错误");
            }
        }else {
            //默认样式
            StyleBuilder styleBuilder = new StyleBuilder();
            String geometryType = geometry.getGeometryType();
            Symbolizer symbolizer = null;
            if (geometryType.equals(Geometry.TYPENAME_POINT)||geometryType.equals(Geometry.TYPENAME_MULTIPOINT)){
                symbolizer = styleBuilder.createPointSymbolizer();
            }
            else  if (geometryType.equals(Geometry.TYPENAME_LINESTRING)||geometryType.equals(Geometry.TYPENAME_MULTILINESTRING)){
                symbolizer = styleBuilder.createLineSymbolizer();
            }
           else if (geometryType.equals(Geometry.TYPENAME_LINEARRING)){
                symbolizer = styleBuilder.createLineSymbolizer();

            }
           else  if (geometryType.equals(Geometry.TYPENAME_POLYGON)||geometryType.equals(Geometry.TYPENAME_MULTIPOLYGON)){
                symbolizer = styleBuilder.createPolygonSymbolizer();
            }
           //Geometry.TYPENAME_GEOMETRYCOLLECTION
           else {
                symbolizer = styleBuilder.createPolygonSymbolizer();
            }
            style = styleBuilder.createStyle(symbolizer);
        }

        return style;
    }

    @Override
    public GeoJsonFeature fileToFeature(String filePath) throws IOException {
        throw new  RuntimeException("不支持当前方法");
    }
}
